﻿namespace mqtttLib.Messages.Base
{

    /// <summary>
    /// MQTT消息
    /// </summary>
    public abstract class MqttMessage
    {
        /// <summary>
        /// 固定头
        /// </summary>
        public FixedHeader FixedHeader { get; protected set; }

        protected MqttMessage(MessageType msgType)
        {
            FixedHeader = new FixedHeader(msgType);
        }

        /// <summary> 
        /// 得到byte[] 类型的数据
        /// </summary> 
        public virtual byte[] GetDataBytes()
        {
            return FixedHeader.GetDataBytes();
        }

        ///// <summary>
        ///// 得到剩余长度占用 字节
        ///// </summary>
        ///// <returns></returns>
        //public int GetRemaingLengthOccupy()
        //{
        //    if (FixedHeader.RemaingLength <= 127)
        //    {
        //        return 1;
        //    }
        //    else if (FixedHeader.RemaingLength <= 16383)
        //    {
        //        return 2;
        //    }
        //    else if (FixedHeader.RemaingLength <= 2097151)
        //    {
        //        return 3;
        //    }
        //    else//268 435 455
        //    {
        //        return 4;
        //    }
        //} 
        /// <summary>
        /// 得到开始偏移量
        /// </summary>
        /// <param name="buffers"></param>
        /// <returns></returns>
        public int GetStartOffset(byte[] buffers)
        {
            int offset = 2;
            if (buffers.Length <= 128)
            {
                offset = 2;
            }
            else if (buffers.Length > 128)
            {
                offset = 3;
            }
            else if (buffers.Length > 16383)
            {
                offset = 4;
            }
            else if (buffers.Length > 2097152)
            {
                offset = 5;
            }
            return offset;
        }
        /// <summary>
        /// 解析
        /// </summary>
        /// <param name="buffers"></param>
        public abstract void GetDataObject(byte[] buffers);

        /// <summary>
        /// 解析消息
        /// </summary>
        /// <param name="buffers"></param>
        /// <returns></returns>
        public static MqttMessage GetDataObjectMessage(byte[] buffers)
        {

            var header = new FixedHeader(buffers);
            var msg = CreateMessage(header.MessageType);
            if (msg != null)
            {
                msg.FixedHeader = header;
                msg.GetDataObject(buffers);
            }
            return msg;

        }

        /// <summary>
        /// 创建消息
        /// </summary>
        /// <param name="msgType"></param>
        /// <returns></returns>
        public static MqttMessage CreateMessage(MessageType msgType)
        {
            switch (msgType)
            {
                case MessageType.CONNECT:
                    return new ConnectMessage();
                case MessageType.CONNACK:
                    return new ConnAckMessage();
                case MessageType.DISCONNECT:
                    return new DisconnectMessage();
                case MessageType.PINGREQ:
                    return new PingReqMessage();
                case MessageType.PINGRESP:
                    return new PingRespMessage();
                case MessageType.PUBACK:
                    return new PublishAckMessage();
                case MessageType.PUBCOMP:
                    return new PublishCompMessage();
                case MessageType.PUBLISH:
                    return new PublishMessage();
                case MessageType.PUBREC:
                    return new PublishRecMessage();
                case MessageType.PUBREL:
                    return new PublishRelMessage();
                case MessageType.SUBSCRIBE:
                    return new SubscribeMessage();
                case MessageType.SUBACK:
                    return new SubscribeAckMessage();
                case MessageType.UNSUBSCRIBE:
                    return new UnsubscribeMessage();
                case MessageType.UNSUBACK:
                    return new UnsubscribeMessage();
                case MessageType.Restart:
                    return new RestartMessage();
                    
                    //throw new Exception("不支持的消息类型");
            }
            return null;
        }
    }



}
